<?php

namespace app\common\model;

use app\api\validate\TaskService;
use app\common\exception\Exception;
use think\console\command\optimize\Schema;
use think\Db;
use think\Hook;
use think\Model;
use think\Session;
use traits\model\SoftDelete;
use think\Lang;
Lang::load(APP_PATH  . '/admin/lang/zh-cn/tasks.php');

/**
 * 任务表
 */
class Tasks extends Model
{
    use SoftDelete;

    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';
    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

    // 追加属性
    protected $append = [
        'createtime_text',
        'images_text',
        'pick_images_text',
        'deliver_images_text',
        'service_start_images_text',
        'service_cancel_images_text',
        'servicing_images_text',
        'serviced_images_text',
        'return_images_text',
        'ext_arr',
        'status_text',
        'curr_flow_text',
        'take_status_text',
        'pick_status_text',
        'service_status_text',
        'return_status_text',
        'settle_status_text',
    ];


    // 任务状态: -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,待维修,4=维修中,5=维修完成,还件中,6=任务已完
    const STATUS_REFUSED = -3;   //已拒绝
    const STATUS_REFUSIND = -2;  //拒绝中
    const STATUS_INVALID = -1;   //接单失败
    const STATUS_WAIT = 0;     //待接单
    const STATUS_TAKE = 1;    //已接单
    const STATUS_PICK = 2;    //已取件
    const STATUS_DELIVER = 3;    //已送达，待维修
    const STATUS_SERVICING = 4;    //维修中
    const STATUS_RETURN = 5;    //维修完成,还件中
    const STATUS_FINISH = 6;    //任务已完成



    public function getCreatetimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['createtime']) ? $data['createtime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getStatusList()
    {
        return ['-3' => __('Status -3'), '-2' => __('Status -2'), '-1' => __('Status -1'), '0' => __('Status 0'), '1' => __('Status 1'), '2' => __('Status 2'), '3' => __('Status 3'), '4' => __('Status 4'), '5' => __('Status 5'), '6' => __('Status 6'),];
    }

    public function getCurrFlowList()
    {
        return ['take' => __('Curr_flow take'), 'pick' => __('Curr_flow pick'), 'service' => __('Curr_flow service'), 'return' => __('Curr_flow return'), 'finish' => __('Curr_flow finish')];
    }

    public function getTakeStatusList()
    {
        return ['-3' => __('Take_status -3'), '-2' => __('Take_status -2'),'-1' => __('Take_status -1'), '0' => __('Take_status 0'), '1' => __('Take_status 1')];
    }

    public function getPickStatusList()
    {
        return ['0' => __('Pick_status 0'), '1' => __('Pick_status 1'), '2' => __('Pick_status 2')];
    }

    public function getServiceStatusList()
    {
        return ['-1' => __('Service_status -1'),'0' => __('Service_status 0'), '1' => __('Service_status 1')];
    }

    public function getReturnStatusList()
    {
        return ['0' => __('Return_status 0'), '1' => __('Return_status 1')];
    }

    public function getSettleStatusList()
    {
        return ['0' => __('Settle_status 0'), '1' => __('Settle_status 1')];
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getCurrFlowTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['curr_flow']) ? $data['curr_flow'] : '');
        $list = $this->getCurrFlowList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getTakeStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['take_status']) ? $data['take_status'] : '');
        $list = $this->getTakeStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getPickStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pick_status']) ? $data['pick_status'] : '');
        $list = $this->getPickStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getServiceStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['service_status']) ? $data['service_status'] : '');
        $list = $this->getServiceStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getReturnStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['return_status']) ? $data['return_status'] : '');
        $list = $this->getReturnStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getSettleStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['settle_status']) ? $data['settle_status'] : '');
        $list = $this->getSettleStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    //任务关联配件
    public function partsItem()
    {
        return $this->hasMany(TaskItem::class,'task_id','id');
    }

    //维修明细
    public function serviceDetails()
    {
        return $this->hasMany(TasksService::class,'task_id','id');
    }

    //图片数组
    public function getImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['images']) ? $data['images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getPickImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pick_images']) ? $data['pick_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getDeliverImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['deliver_images']) ? $data['deliver_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getServiceStartImagesTextAttr($value,$data)
    {
        $value = $value ? $value : (isset($data['service_start_images']) ? $data['service_start_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getServiceCancelImagesTextAttr($value,$data)
    {
        $value = $value ? $value : (isset($data['service_cancel_images']) ? $data['service_cancel_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getServicingImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['servicing_images']) ? $data['servicing_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getServicedImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['serviced_images']) ? $data['serviced_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function getReturnImagesTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['return_images']) ? $data['return_images'] : '');
        if (!$value){
            return [];
        }
        $arr = explode(',',$value);
        foreach ($arr as &$item){
            $item = cdnurl($item,true);
        }
        return $arr;
    }

    public function setExt($item, $field, $origin = [])
    {
        $newExt = array_merge($origin, $field);

        $itemExt = $item['ext_arr'];

        return array_merge($itemExt, $newExt);
    }

    public function getExtArrAttr($value, $data)
    {
        $ext = (isset($data['ext']) && $data['ext']) ? json_decode($data['ext'], true) : [];
        $ext['expired_time_text'] = !isset($ext['expired_time']) || !$ext['expired_time']  ? '' :date("Y-m-d H:i:s", $ext['expired_time']);
        $ext['invalid_time_text'] = !isset($ext['invalid_time']) || !$ext['invalid_time'] ? '' :date("Y-m-d H:i:s", $ext['invalid_time']);
        $ext['take_time_text'] = !isset($ext['take_time']) || !$ext['take_time'] ? '' :date("Y-m-d H:i:s", $ext['take_time']);
        $ext['refuse_time_text'] = !isset($ext['refuse_time']) || !$ext['refuse_time'] ? '' :date("Y-m-d H:i:s", $ext['refuse_time']);
        $ext['pick_time_text'] = !isset($ext['pick_time']) || !$ext['pick_time'] ? '' :date("Y-m-d H:i:s", $ext['pick_time']);
        $ext['deliver_time_text'] = !isset($ext['deliver_time']) || !$ext['deliver_time'] ? '' :date("Y-m-d H:i:s", $ext['deliver_time']);
        $ext['serviced_time_text'] = !isset($ext['serviced_time']) || !$ext['serviced_time'] ? '' :date("Y-m-d H:i:s", $ext['serviced_time']);
        $ext['service_start_time_text'] = !isset($ext['service_start_time']) || !$ext['service_start_time'] ? '' :date("Y-m-d H:i:s", $ext['service_start_time']);
        $ext['service_cancel_time_text'] = !isset($ext['service_cancel_time']) || !$ext['service_cancel_time'] ? '' :date("Y-m-d H:i:s", $ext['service_cancel_time']);
        $ext['return_time_text'] = !isset($ext['return_time']) || !$ext['return_time'] ? '' :date("Y-m-d H:i:s", $ext['return_time']);
        $ext['refuse_pass_time_text'] = !isset($ext['refuse_pass_time']) || !$ext['refuse_pass_time'] ? '' :date("Y-m-d H:i:s", $ext['refuse_pass_time']);
        $ext['pick_expired_time_text'] = !isset($ext['pick_expired_time']) || !$ext['pick_expired_time'] ? '' :date("Y-m-d H:i:s", $ext['pick_expired_time']);
        return $ext;
    }

    public function pickUser()
    {
        return $this->hasOne(User::class,'id','pick_uid')->field('id,nickname,avatar');
    }

    public function insuranceCompany()
    {
        return $this->hasOne(InsuranceCompany::class,'id','insurance_company_id')->field('id,name');
    }

    public function settle()
    {
        return $this->hasOne(TaskSettle::class,'task_id','id');
    }

    public function returnType()
    {
        return $this->hasOne(ReturnType::class,'id','return_id');
    }

    //获取任务单详情
    public static function getDetail($id)
    {
        return self::with('partsItem,pick_user,insurance_company,return_type,service_details')->where(['id' => $id])->find();
    }

    //数量统计
    public static function getTypeCount($flag = 'all')
    {
        //如果要查询还件的列表，不判断权限，直接获取全部列表

        //全部统计
        if ($flag == 'all'){
            $count['take'] = self::where(['curr_flow'=>'take'])->count();
            $count['pick'] = self::where(['curr_flow'=>'pick'])->count();
            $count['service'] = self::where(['curr_flow'=>'service'])->count();
            $count['return'] = self::where(['curr_flow'=>'return'])->count();
            $count['all'] = $count['take'] + $count['pick'] + $count['service'] + $count['return'];
        }

        //取件人的统计
        if ($flag == 'pick'){
            $user = User::info();
            $count['take'] = self::where(['curr_flow'=>'take'])->where('pick_uid',$user->id)->count();
            $count['pick'] = self::where(['curr_flow'=>'pick'])->where('pick_uid',$user->id)->count();
            $count['service'] = self::where(['curr_flow'=>'service'])->where('pick_uid',$user->id)->count();
            $count['return'] = self::where(['curr_flow'=>'return'])->count();
            $count['all'] = $count['take'] + $count['pick'] + $count['service'] + $count['return'];
        }

        //维修人的订单统计,只能看到维修人是自己的任务列表,和所有的待维修列表
        if ($flag == 'service'){
            $user = User::info();
            $count['take'] = self::where(['curr_flow'=>'take'])->where('service_uid',$user->id)->count();
            $count['pick'] = self::where(['curr_flow'=>'pick'])->where('service_uid',$user->id)->count();
            $count['service'] = (self::where(['curr_flow'=>'service'])->where('service_uid',$user->id)->count()) + self::where(['curr_flow'=>'service'])->where('status',Tasks::STATUS_DELIVER)->count();
            $count['return'] = self::where(['curr_flow'=>'return'])->count();
            $count['all'] = $count['take'] + $count['pick'] + $count['service'] + $count['return'];
        }

        //其它人只能看到还件列表
        if ($flag == 'other'){
            $count['take'] = 0;
            $count['pick'] = 0;
            $count['service'] = 0;
            $count['return'] = self::where(['curr_flow'=>'return'])->count();
            $count['all'] = $count['take'] + $count['pick'] + $count['service'] + $count['return'];
        }

        return $count;
    }


    //获取列表
    public static function getLists($params,$flag = 'all')
    {
        //默认参数
        $type = 'all';
        $starttime = '';
        $endtime = date('Y-m-d');
        extract($params);

        //如果是普通人权限，且要查看的不是待还件状态，看不到列表
        if ($flag == 'other' && $type != Tasks::STATUS_RETURN && $type != 'all'){
            return null;
        }

        $where = [];
        $user = User::info();

        //如果是取件人，只能看到取件人是自己的任务列表
        if ($flag == 'pick'){
            $where['pick_uid'] = $user->id;
        }

        //如果是维修人，只能看到维修人是自己的任务列表,和所有的待维修列表
        if ($flag == 'service' && $type != Tasks::STATUS_DELIVER){
            $where['service_uid'] = $user->id;
        }

        //时间段筛查
        if (isset($starttime) && $starttime && isset($endtime) && $endtime) {
            $where['createtime'] = ['between', [strtotime($starttime), strtotime($endtime. '+1 day')]];
        }

        //任务状态筛查:  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,待维修,4=维修中,5=维修完成,还件中,6=任务已完成
        if ($type != 'all'){
            $where['status'] = $type;
        }

        if ($type == -5){
            $where['status'] = ['in',[Tasks::STATUS_REFUSIND,Tasks::STATUS_REFUSED]];
        }

        //如果要查询还件的列表，不判断权限，直接获取全部列表
        if ($type == Tasks::STATUS_RETURN){
            unset($where['service_uid']);
            unset($where['pick_uid']);
        }

        //如果是普通人权限，且要查看所有列表，只能看到待还件的
        if ($flag == 'other' && $type == 'all'){
            $where['status'] = 5;
        }

        //搜索关键词
        if (isset($keywords) && $keywords) {
            $where['car_number | report_number | models | name_4s | pick_nickname | insurance_company_name'] = ['like','%'.$keywords.'%'];
        }

        //最终数据
        return self::with('partsItem,pick_user,insurance_company,return_type')->where($where)->order('createtime desc')->paginate(10);
    }


    //添加
    public static function operCreate($params)
    {
        $user = User::info();
        $remark = '';
        $pick_hours = 1;
        $name_4s = '';
        extract($params);
        $areaNameArray = explode("-", $area_text);
        try {
            $province = AddressArea::get(['name' => $areaNameArray[0], 'level' => 1]);
            $city = AddressArea::get(['name' => $areaNameArray[1], 'level' => 2]);
            $area = AddressArea::get(['name' => $areaNameArray[2], 'pid' => $city->id, 'level' => 3]);
            if(!$province || !$city || !$area) {
                new Exception('暂不支持,请手动选择行政区');
            }
        } catch (\Exception $e) {
            new Exception('暂不支持,请手动选择行政区');
        }
        if (count($images) > 9){
            new Exception('修复前照片不得超过9张');
        }
        if ($pick_hours > 72 || $pick_hours < 1) {
            new Exception('取件时效最长不得超过72小时');
        }
        //取件人
        $pick_user = User::where('id',$pick_uid)->find();
        if (!$pick_user){
            new Exception('取件人不存在');
        }
        //创建任务
        $row = Db::transaction(function () use (
            $user,
            $date,
            $report_number,
            $models,
            $car_number,
            $name_4s,
            $insurance_company_id,
            $receptionist,
            $pick_user,
            $sure_name,
            $return_id,
            $pick_hours,
            $price,
            $mobile_jd,
            $mobile_ds,
            $remark,
            $images,
            $content,
            $province,
            $city,
            $area,
            $address
        ) {
            $task_data = [];
            $task_data['mobile_jd'] = $mobile_jd;
            $task_data['mobile_ds'] = $mobile_ds;
            $task_data['user_id'] = $user->id;
            $task_data['user_nickname'] = $user->nickname;
            $task_data['order_sn'] = self::getSn($user->id);
            $task_data['date'] = $date;
            $task_data['report_number'] = $report_number;
            $task_data['models'] = $models;
            $task_data['car_number'] = $car_number;
            $task_data['province_name'] = $province->name;
            $task_data['city_name'] = $city->name;
            $task_data['area_name'] = $area->name;
            $task_data['province_id'] = $province->id;
            $task_data['city_id'] = $city->id;
            $task_data['area_id'] = $area->id;
            $task_data['address'] = $address;
            $task_data['name_4s'] = $name_4s;
            $task_data['insurance_company_id'] = $insurance_company_id;
            $task_data['receptionist'] = $receptionist;
            $task_data['pick_uid'] = $pick_user->id;
            $task_data['pick_nickname'] = $pick_user->nickname;
            $task_data['sure_name'] = $sure_name;
            $task_data['return_id'] = $return_id;
            $task_data['pick_hours'] = $pick_hours;
            $task_data['price'] = $price;
            $task_data['remark'] = $remark;
            $task_data['images'] = join(',', $images);
            $task_data['status'] = self::STATUS_WAIT;    //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task_data['curr_flow'] = 'take';  //任务当前流:take=接单,pick=取件,service=维修,return=还件
            $task_data['take_status'] = 0;  //任务状态:-1=接单失败,0=待接单,1=已接单
            $task_data['pick_status'] = 0;  //取件状态:0=待取件,1=已取件,2=已送达
            $task_data['service_status'] = 0;  //维修状态:0=维修中,1=维修完成
            $task_data['return_status'] = 0;  //还件状态:0=还件中,1=已还件
            $task_data['settle_status'] = -1;  //结算状态:-1=不可结算,0=待结算,1=已结算
            $task_data['ext'] = json_encode(['expired_num'=>0]);      //到期次数
            $task = new self();
            $task->allowField(true)->save($task_data);

            //添加任务配件
            foreach ($content as $item) {
                $part = Parts::where('id',$item['part_id'])->find();
                if (!$part){
                    new Exception('修复件不存在，请重新选择');
                }
                $task_item = new TaskItem();
                $task_item->user_id = $user->id;
                $task_item->task_id = $task->id;
                $task_item->part_id = $part->id;
                $task_item->part_name = $part['name'];
                $task_item->part_fee = $part['fee'];
                $task_item->number = $item['number'];
                $task_item->total_fee = bcmul($part['fee'], $item['number'], 2);
                $task_item->remark = $item['remark'];
                $task_item->save();
            }

            //审批创建后的钩子
            $data['task'] = $task;
            Hook::listen('task_create_after',$data);

            // 重新获取
            $row = self::where('id', $task['id'])->find();

            //发送微信通知
            $params['task'] = $row;
            $params['action'] = 'created';
            Hook::listen('send_message',$params);

            return $row;
        });
        return $row;
    }

    //编辑
    public static function operEdit($params)
    {
        $user = User::info();
        $remark = '';
        $pick_hours = 1;
        extract($params);
        $areaNameArray = explode("-", $area_text);
        try {
            $province = AddressArea::get(['name' => $areaNameArray[0], 'level' => 1]);
            $city = AddressArea::get(['name' => $areaNameArray[1], 'level' => 2]);
            $area = AddressArea::get(['name' => $areaNameArray[2], 'pid' => $city->id, 'level' => 3]);
            if(!$province || !$city || !$area) {
                new Exception('暂不支持,请手动选择行政区');
            }
        } catch (\Exception $e) {
            new Exception('暂不支持,请手动选择行政区');
        }
        if (count($images) > 9){
            new Exception('修复前照片不得超过9张');
        }
        if ($pick_hours > 72 || $pick_hours < 1) {
            new Exception('取件时效最长不得超过72小时');
        }
        //取件人
        $pick_user = User::where('id',$pick_uid)->find();
        if (!$pick_user){
            new Exception('取件人不存在');
        }
        //编辑任务
        $row = Db::transaction(function () use (
            $id,
            $user,
            $date,
            $report_number,
            $models,
            $car_number,
            $name_4s,
            $insurance_company_id,
            $receptionist,
            $pick_user,
            $sure_name,
            $return_id,
            $pick_hours,
            $price,
            $mobile_jd,
            $mobile_ds,
            $remark,
            $images,
            $content,
            $province,
            $city,
            $area,
            $address
        ) {
            $task_data = [];
            $task_data['mobile_jd'] = $mobile_jd;
            $task_data['mobile_ds'] = $mobile_ds;
            $task_data['user_id'] = $user->id;
            $task_data['user_nickname'] = $user->nickname;
            $task_data['date'] = $date;
            $task_data['report_number'] = $report_number;
            $task_data['models'] = $models;
            $task_data['car_number'] = $car_number;
            $task_data['province_name'] = $province->name;
            $task_data['city_name'] = $city->name;
            $task_data['area_name'] = $area->name;
            $task_data['province_id'] = $province->id;
            $task_data['city_id'] = $city->id;
            $task_data['area_id'] = $area->id;
            $task_data['address'] = $address;
            $task_data['name_4s'] = $name_4s;
            $task_data['insurance_company_id'] = $insurance_company_id;
            $task_data['receptionist'] = $receptionist;
            $task_data['pick_uid'] = $pick_user->id;
            $task_data['pick_nickname'] = $pick_user->nickname;
            $task_data['sure_name'] = $sure_name;
            $task_data['return_id'] = $return_id;
            $task_data['pick_hours'] = $pick_hours;
            $task_data['price'] = $price;
            $task_data['remark'] = $remark;
            $task_data['images'] = join(',', $images);
            $task_data['status'] = self::STATUS_WAIT;    //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task_data['curr_flow'] = 'take';  //任务当前流:take=接单,pick=取件,service=维修,return=还件
            $task_data['take_status'] = 0;  //任务状态:-1=接单失败,0=待接单,1=已接单
            $task_data['pick_status'] = 0;  //取件状态:0=待取件,1=已取件,2=已送达
            $task_data['service_status'] = 0;  //维修状态:0=维修中,1=维修完成
            $task_data['return_status'] = 0;  //还件状态:0=还件中,1=已还件
            $task_data['settle_status'] = -1;  //结算状态:-1=不可结算,0=待结算,1=已结算
            $task_data['ext'] = json_encode(['expired_num'=>0]);      //到期次数
            $task_data['edittime'] = time();    //编辑发布时间
            $task_data['id'] = $id;
            $task = self::update($task_data);


            //删除之前的任务配件信息
            TaskItem::where('task_id',$id)->delete();
            //添加任务配件
            foreach ($content as $item) {
                $part = Parts::where('id',$item['part_id'])->find();
                if (!$part){
                    new Exception('修复件不存在，请重新选择');
                }
                $task_item = new TaskItem();
                $task_item->user_id = $user->id;
                $task_item->task_id = $id;
                $task_item->part_id = $part->id;
                $task_item->part_name = $part['name'];
                $task_item->part_fee = $part['fee'];
                $task_item->number = $item['number'];
                $task_item->total_fee = bcmul($part['fee'], $item['number'], 2);
                $task_item->remark = $item['remark'];
                $task_item->save();
            }

            //任务创建后的钩子
            $data['task'] = $task;
            Hook::listen('task_create_after',$data);

            // 重新获取
            $row = self::where('id', $task['id'])->find();

            //发送微信通知
            $params['task'] = $row;
            $params['action'] = 'created';
            Hook::listen('send_message',$params);

            return $row;
        });
        return $row;
    }

    //确认接单
    public static function operTake($id)
    {
        $user = User::info();
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->pick_uid != $user->id){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'take' || $task->take_status != 0){
            new Exception('当前任务或已被接');
        }

        //接单
        $row = Db::transaction(function () use (
            $user,
            $task
        ) {
            //接单时效 = 当前时间 - 订单创建或重新发布的时间
            $take_range = time() - $task->createtime;
            if ($task->edittime){
                $take_range = time() - $task->edittime;
            }
            //修改任务状态,计算 取件过期时效
            $take_expired_time = time() + ($task->pick_hours * 3600);
            $task->status = self::STATUS_TAKE;   //任务状态:-3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,维修中,4=维修完成,还件中,5=任务已完成
            $task->curr_flow = 'pick';  //已接单自动转为取件流程
            $task->take_status = 1;
            $task->ext = json_encode($task->setExt($task, ['take_time' => time(),'pick_expired_time'=>$take_expired_time]));      // 接单时间
            $task->take_range = $take_range;
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','take',TaskAction::$memo_arr[2]);

            //接单后删除队列
            \think\Queue::push('\app\common\job\TaskAutoOper@autoClose', ['task' => $task,'action'=>'operTake'], 'lingtu');

            return $task;
        });
        return $row;
    }

    //拒绝接单
    public static function operRefuse($id,$remark)
    {
        $user = User::info();
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->pick_uid != $user->id){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'take' || $task->take_status != 0){
            new Exception('当前任务或已取消');
        }
        //拒绝接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $remark
        ) {
            $task_ext = $task->ext_arr;
            //将拒绝次数加入扩展字段
            $task_ext['refuse_time'] = time();  // 拒绝时间
            $task_ext['refuse_num'] = isset($task_ext['refuse_num']) ? ($task_ext['refuse_num'] + 1) : 1 ;  //任务拒绝次数
            //修改任务状态
            $task->curr_flow = 'take';
            $task->status = self::STATUS_REFUSIND;
            $task->take_status = -2;
            $task->refuse_remark = $remark;
            $task->ext = json_encode($task_ext);
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','refuse',TaskAction::$memo_arr[3]);

            //拒绝接单删除计时队列
            \think\Queue::push('\app\common\job\TaskAutoOper@autoClose', ['task' => $task,'action'=>'operRefuse'], 'lingtu');

            // 重新获取
            $row = self::where('id', $task['id'])->find();
            return $row;
        });
        return $row;

    }


    //取消拒接
    public static function operRefuseCancel($id)
    {

        $user = User::info();
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->pick_uid != $user->id){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'take' || $task->take_status != -2){
            new Exception('当前任务或已取消');
        }
        //取消拒接
        $row = Db::transaction(function () use (
            $user,
            $task
        ) {
            //修改任务状态
            $task->refuse_remark = '';
            $task->curr_flow = 'take';
            $task->status = self::STATUS_WAIT;
            $task->take_status = 0;
            $task->ext = json_encode($task->setExt($task, ['refuse_cancel_time' => time()]));      // 取消拒接时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','refuse_cancel',TaskAction::$memo_arr[12]);

            //开始任务倒计时队列
            $data['task'] = $task;
            Hook::listen('task_create_after',$data);

            // 重新获取
            $row = self::where('id', $task['id'])->find();
            return $row;
        });
        return $row;
    }

    //拒接审核
    public static function operRefuseStatus($task,$user,$oper)
    {
        //审核通过
        if ($oper == 'yes'){
            $row = Db::transaction(function () use (
                $task,
                $user
            ) {
                //同意拒接操作，任务变拒绝接单状态
                $task->curr_flow = 'take';
                $task->status = self::STATUS_REFUSED;
                $task->take_status = -3;
                $task->ext = json_encode($task->setExt($task, ['refuse_pass_time' => time(),'invalid_time'=>time()]));      // 审核通过时间
                $task->save();

                //添加任务动作
                TaskAction::operAdd($task,$user,'user','refuse_pass',TaskAction::$memo_arr[10]);

                return $task;
            });
        }else{
            //审核不通过，不同意拒接操作，任务将重新开始倒计时
            $row = Db::transaction(function () use (
                $task,
                $user
            ) {
                $task->curr_flow = 'take';
                $task->status = self::STATUS_WAIT;
                $task->take_status = 0;
                $task->ext = json_encode($task->setExt($task, ['refuse_not_pass_time' => time()]));      // 审核不通过时间
                $task->save();

                //添加任务动作
                TaskAction::operAdd($task,$user,'user','refuse_not_pass',TaskAction::$memo_arr[9]);

                //开始任务倒计时队列
                $data['task'] = $task;
                Hook::listen('task_create_after',$data);

                return $task;
            });
        }
        return $row;
    }

    //确认取件
    public static function operPick($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->pick_uid != $user->id){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'pick' || $task->take_status != 1){
            new Exception('当前任务流不可取件');
        }

        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $images
        ) {
            //修改任务状态
            $task->status = self::STATUS_PICK;   //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'pick';
            $task->pick_status = 1; //取件状态:1=已取件,2=已送达
            $task->pick_images = join(',', $images);
            $task->ext = json_encode($task->setExt($task, ['pick_time' => time()]));      // 取件时间
            $task->take_pick_range = time() - $task->ext_arr['take_time'];  //取件用时 = 当前时间 - 接单时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','pick',TaskAction::$memo_arr[4]);

            //取件成功，发送微信通知
            $params['task'] = $task;
            $params['action'] = 'picked';
            Hook::listen('send_message',$params);

            return $task;
        });
        return $row;
    }

    //确认送达
    public static function operDeliver($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->pick_uid != $user->id){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'pick' || $task->take_status != 1 || $task->pick_status != 1){
            new Exception('当前任务流不可确认送达');
        }

        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $images
        ) {
            //修改任务状态
            $task->deliver_uid = $user->id;
            $task->deliver_nickname = $user->nickname;
            $task->status = self::STATUS_SERVICING;   //任务状态:-3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,待维修,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'service';   //已送达自动转为维修任务流
            $task->pick_status = 2; //取件状态:1=已取件,2=已送达
            $task->service_status = 1; //维修状态:0=待维修,1=维修中,2=维修完成,-1=不可维修
            $task->deliver_images = join(',', $images);
            $task->ext = json_encode($task->setExt($task, ['deliver_time' => time()]));      // 取件送达时间
            $task->pick_range = time() - $task->ext_arr['pick_time'];  //取件流时效 = 当前时间 - 取件时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','deliver',TaskAction::$memo_arr[5]);

            return $task;
        });
        return $row;
    }

    //开始维修
    public static function operServiceStart($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        //判断是否是取件人或者维修人
        if (!UserGroup::isAdmin($user->id) && $task->pick_uid != $user->id && !UserGroup::isPicker($user->id) && !UserGroup::isService($user->id)){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'service' || $task->take_status != 1 || $task->pick_status != 2){
            new Exception('当前任务流不可维修');
        }
        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $images
        ) {
            //修改任务状态
            $task->service_uid = $user->id;
            $task->service_nickname = $user->nickname;
            $task->status = self::STATUS_SERVICING;   //任务状态:-3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,待维修,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'service';   //维修中任务流
            $task->service_status = 1; //维修状态:0=待维修,1=维修中,2=维修完成
            $task->service_start_images = join(',', $images);
            $task->ext = json_encode($task->setExt($task, ['service_start_time' => time()]));      // 维修开始的时间
            $task->pick_service_range = time() - $task->ext_arr['deliver_time'];  //维修准备用时 = 当前时间 - 取件送达时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','service_start',TaskAction::$memo_arr[13]);

            return $task;
        });
        return $row;
    }

    //无法维修
    public static function operServiceCancel($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        //判断是否是取件人或者维修人
        if (!UserGroup::isAdmin($user->id) && $task->pick_uid != $user->id && !UserGroup::isPicker($user->id) && !UserGroup::isService($user->id)){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'service' || $task->take_status != 1 || $task->pick_status != 2){
            new Exception('当前任务流不可维修');
        }
        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $service_cancel_memo,
            $images
        ) {
            //修改任务状态，无法维修转入还件任务流
            $task->service_uid = $user->id;
            $task->service_nickname = $user->nickname;
            $task->status = self::STATUS_RETURN;   //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'return';   //无法维修任务流
            $task->service_status = "-1"; //维修状态:0=待维修,1=维修中,2=维修完成,-1=无法维修
            $task->service_cancel_images = join(',', $images);
            $task->service_cancel_memo = $service_cancel_memo;
            $task->ext = json_encode($task->setExt($task, ['service_cancel_time' => time(),'serviced_time'=>time()]));      // 无法维修的时间 维修完成的时间
            $task->service_range = time() - $task->ext_arr['deliver_time'];  //维修流时效 = 当前时间 - 送达时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','service_cancel',TaskAction::$memo_arr[14]);

            return $task;
        });
        return $row;
    }

    //维修明细
    public static function OperServiceDetails($params)
    {
        $user = User::info();
        $num = 1;
        extract($params);
        if (!ctype_digit($num)){
            new Exception('修复数量只能是整数');
        }
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        //如果用户不是超级管理员，判断是否是取件人或者维修人
        if (!UserGroup::isAdmin($user->id) && $task->pick_uid != $user->id && !UserGroup::isPicker($user->id) && !UserGroup::isService($user->id)){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'service'){
            new Exception('当前任务流不可维修');
        }
        $art = PartsArt::get($art_id);
        if (!$art) {
            new Exception('配件工艺不存在');
        }
        return TasksService::create([
            'task_id'           => $task->id,
            'user_id'           => $user->id,
            'user_nickname'     => $user->nickname,
            'art_id'            => $art['id'],
            'art_name'          => $art['name'],
            'content'           => $content,
            'num'               => $num,
            'images'            => join(',',$images),
            'art_fee'           => $art['fee'],
            'total_fee'         => bcmul($art['fee'], $num, 2),
        ]);
    }

    //维修完成
    public static function operService($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }

        //如果用户不是超级管理员，判断是否是取件人或者维修人
        if (!UserGroup::isAdmin($user->id) && $task->pick_uid != $user->id && !UserGroup::isPicker($user->id) && !UserGroup::isService($user->id)){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'service' || $task->take_status != 1 || $task->pick_status != 2){
            new Exception('当前任务流不可维修完成');
        }

        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $servicing_images,
            $serviced_images
        ) {
            //修改任务状态
            $task->service_end_uid = $user->id;
            $task->service_end_nickname = $user->nickname;
            $task->status = self::STATUS_RETURN;   //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'return';   //维修完成自动转为还件任务流
            $task->service_status = 2; //维修状态:0=待维修,1=维修中,2=维修完成
            $task->servicing_images = join(',', $servicing_images);
            $task->serviced_images = join(',', $serviced_images);
            $task->ext = json_encode($task->setExt($task, ['serviced_time' => time()]));      // 维修完成时间
            $task->service_range = time() - $task->ext_arr['deliver_time'];  //维修流时效 = 当前时间 - 送达时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','service',TaskAction::$memo_arr[6]);

            //发送微信通知
            $params['task'] = $task;
            $params['action'] = 'serviced';
            Hook::listen('send_message',$params);

            return $task;
        });
        return $row;
    }

    //确认还件
    public static function operReturn($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        //判断是否是超级管理员 取件人 或者是否有取件人权限
        if (!UserGroup::isAdmin($user->id) && $task->pick_uid != $user->id && !UserGroup::isPicker($user->id) && !UserGroup::isService($user->id)){
            new Exception('您没有操作权限');
        }
        if ($task->curr_flow != 'return' || $task->status != Tasks::STATUS_RETURN){
            new Exception('当前任务流不可确认还件');
        }

        //接单
        $row = Db::transaction(function () use (
            $user,
            $task,
            $images
        ) {
            //修改任务状态
            $task->return_uid = $user->id;
            $task->return_nickname = $user->nickname;
            $task->status = self::STATUS_FINISH;   //任务状态  -3=已拒绝接单-2=拒绝接单中,-1=接单失败,0=待接单,1=已接单,待取件，2=已取件,3=取件已送达,4=维修中,5=维修完成,还件中,6=任务已完成
            $task->curr_flow = 'finish';   //已还件自动转化为完成任务流
            $task->return_status = 1; //还件状态:0=还件中,1=已还件
            $task->settle_status = 0; //结算状态:-1=不可结算,0=待结算,1=已结算
            $task->return_images = join(',', $images);
            $task->ext = json_encode($task->setExt($task, ['return_time' => time()]));      // 还件时间
            $task->return_range = time() - $task->ext_arr['serviced_time'];  //还件时效 = 当前时间 - 维修完成时间
            $task->range = time() - $task->createtime;  //总计时效 = 当前时间 - 维修完成时间
            $task->finishtime = time();
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','return',TaskAction::$memo_arr[7]);
            TaskAction::operAdd($task,$user,'user','finish',TaskAction::$memo_arr[8]);

            //任务完成后，计入取件人提成
            $data['task'] = $task;
            Hook::listen('task_finish_after',$data);

            return $task;
        });
        return $row;
    }

    //选择任务单 - 任务列表
    public static function getTasks()
    {
        $where['curr_flow'] = ['in',['pick','service','return']];
        return self::where($where)->order('updatetime desc')->select();
    }

    //结算列表
    public static function getSettleLists($params)
    {
        $starttime = '';
        $endtime = date('Y-m-d');
        $keywords = '';
        extract($params);
        $where['curr_flow'] = 'finish';
        $where['return_status'] = 1;
        if (isset($type) && $type != 'all') {
            $where['settle_status'] = $type;
        }
        if (isset($starttime) && $starttime && isset($endtime) && $endtime) {
            $where['createtime'] = ['between', [strtotime($starttime), strtotime($endtime. '+1 day')]];
        }
        if ($keywords){
            $where['car_number | report_number | models | name_4s | pick_nickname | insurance_company_name'] = ['like','%'.$keywords.'%'];
        }
        return self::with('pick_user,insurance_company,settle')->where($where)->order('createtime desc')->paginate(10);
    }

    //立即结算
    public static function operSettlement($params)
    {
        $user = User::info();
        extract($params);
        $task = self::where('id',$id)->find();
        if (!$task) {
            new Exception('任务不存在');
        }
        if ($task->curr_flow != 'finish' || $task->return_status != 1){
            new Exception('当前任务不可结算');
        }
        if ( $task->settle_status == 1) {
            new Exception('当前任务已结算');
        }
        //结算
        $row = Db::transaction(function () use (
            $user,
            $task,
            $return_id,
            $price,
            $remark
        ) {
            //修改任务状态
            $task->status = 7;
            $task->settle_status = 1; //结算状态:0=待结算,1=已结算
            $task->ext = json_encode($task->setExt($task, ['settle_time' => time()]));      // 结算时间
            $task->save();
            //添加任务动作
            TaskAction::operAdd($task,$user,'user','settle',TaskAction::$memo_arr[11]);
            //添加结算信息
            TaskSettle::create([
                'task_id'       => $task->id,
                'user_id'       => $user->id,
                'return_id'     => $return_id,
                'price'         => $price,
                'remark'        => $remark
            ]);
            return $task;
        });
        return $row;
    }

    // 获取订单号
    public static function getSn($user_id)
    {
        $rand = $user_id < 9999 ? mt_rand(100000, 999999) : mt_rand(100, 99999);
        $order_sn = date('Yhis') . $rand;

        $id = str_pad($user_id, (18 - strlen($order_sn)), '0', STR_PAD_BOTH);

        return $order_sn . $id;
    }
}
